package com.sq.util.web;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JavaType;
import com.sq.util.JsonUtil;
import com.sq.util.encrypt.SignUtil;
import com.sq.util.exception.VisualException;
import com.sq.util.view.JsonView;

/**
 * @author sq
 *
 */
public class WebServiceRequestor {

    private static final Logger log = LoggerFactory.getLogger(WebServiceRequestor.class);

    private String baseUri;

    private String appid;

    private String key;

    private boolean logRequestInfo = true;

    public WebServiceRequestor(String baseUri, String appid, String key) {
        this(baseUri, appid, key, true);
    }

    public WebServiceRequestor(String baseUri, String appid, String key, boolean logRequestInfo) {
        super();
        this.baseUri = baseUri;
        this.appid = appid;
        this.key = key;
        this.logRequestInfo = logRequestInfo;
    }

    public <T> List<T> postUrlForList(String queryUrl, Class<T> cls, String data) {
        String content = postUrl(queryUrl, data);
        return convertToList(content, cls);
    }

    public static <T> T convertToObject(String content, Class<T> cls) {
        JavaType javaType = JsonUtil.constructParametricType(JsonBO.class, cls);
        try {
            JsonBO<T> data = (JsonBO<T>) JsonUtil.readValue(content, javaType);
            return getReturnObject(data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VisualException(e.getMessage());
        }
    }

    @SuppressWarnings({ "unchecked" })
    public static <T> List<T> convertToList(String content, Class<T> cls) {
        JavaType javaType = JsonUtil.constructParametricType(JsonBO.class,
                JsonUtil.constructParametricType(List.class, cls));
        try {
            JsonBO<List<T>> data = (JsonBO<List<T>>) JsonUtil.readValue(content, javaType);
            return getReturnObject(data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VisualException(e.getMessage());
        }
    }

    public <T> T postUrlForObject(String queryUrl, Class<T> cls, String data) {
        String content = postUrl(queryUrl, data);
        return convertToObject(content, cls);
    }

    private String postUrl(String queryUrl, String data) {
        String ts = "" + System.currentTimeMillis();
        String sign = SignUtil.md5((appid + data + key + ts).getBytes(StandardCharsets.UTF_8));
        Map<String, String> params = new HashMap<>();
        params.put("appid", appid);
        params.put("data", data);
        params.put("ts", ts);
        params.put("sign", sign);
        String content = null;
        String url = baseUri + queryUrl;
        try {
            content = HttpPostUtil.execute(url, params);
            if (logRequestInfo) {
                log.info("请求[{}],参数[{}],返回[{}]", new Object[] { url, params, content });
            }
            return content;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            log.error("请求出错[{}],参数[{}]", new Object[] { url, params });
            throw new VisualException(e.getMessage());
        }
    }

    @SuppressWarnings({ "unchecked" })

    private static <T> T getReturnObject(JsonBO<T> data) {
        int code = data.getCode();
        VisualException.isTrue(code == JsonView.SUCCESS, data.getMsg());
        return data.getData();
    }

}
